// HTTPS用到
#include <any>

#include "./HttpServer.h"
// #include "./HttpRequest.h"
// #include "./HttpContext.h"
// #include "./HttpResponse.h"

HttpServer::HttpServer(EventLoop *loop,
                       const InetAddress &listenAddr,
                       TcpServer::ListenOption listenOpt,
                       const std::string &threadName)
    : tcpServer_(loop, listenAddr, listenOpt, threadName),
      httpCallback_(std::move(defaultHttpCallback))
{
    this->tcpServer_.setThreadNum(3);

    // this->tcpServer_.setConnectionCallback(
    //     std::bind(&HttpServer::onConnectionCallback, this, std::placeholders::_1));
    // this->tcpServer_.setReadWriteCallback(
    //     std::bind(&HttpServer::onReadWriteCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    this->tcpServer_.setConnectionCallback(
        [this](const TcpConnectionPtr &conn)
        {
            this->onConnectionCallback(conn);
        });
    this->tcpServer_.setReadWriteCallback(
        [this](const TcpConnectionPtr &conn, Buffer *buf, Timestamp receiveTime)
        {
            this->onReadWriteCallback(conn, buf, receiveTime);
        });
}

void HttpServer::defaultHttpCallback(const HttpRequest &request, HttpResponse *responseponse)
{
    responseponse->setStatusCode(HttpResponse::StatusCode::NotFound404);
    responseponse->setStatusMessage("Not Found");
    responseponse->setNeedCloseConnection(true);
}

void HttpServer::onConnectionCallback(const TcpConnectionPtr &conn)
{
    if (conn->isConnected())
    {
        LOG_INFO("new Connection arrived");
    }
    else
    {
        LOG_INFO("Connection closed");
    }
}

void HttpServer::onReadWriteCallback(const TcpConnectionPtr &conn, Buffer *buf, Timestamp receiveTime)
{
    LOG_INFO("onReadWriteCallback");
    std::unique_ptr<HttpContext> context(new HttpContext);

    std::string requestuestMessage = "Request Data: \n";
    requestuestMessage += buf->getAllReadableDataDebug();
    LOG_DEBUG(requestuestMessage.c_str());

    // 解析请求
    bool isOk = context->parseRequest(buf, receiveTime);
    if (!isOk)
    {
        LOG_INFO("parseRequest failed!");
        conn->sendData("HTTP/1.1 400 Bad Request\r\n\r\n");
        conn->shutdown();
    }

    if (context->isRequestParseStateGotAll()) // 二次校验
    {
        LOG_INFO("parseRequest success!");
        this->handleRequest(conn, context->getRequest());
        context->reset();
    }
}

void HttpServer::handleRequest(const TcpConnectionPtr &conn, const HttpRequest &request)
{
    std::string connection = request.getHeader("Connection");
    bool needClose = connection == "close" ||
                     (request.getVersion() == HttpRequest::Version::Http10 && connection != "Keep-Alive"); // 短连接

    // 响应
    HttpResponse response(needClose);

    this->httpCallback_(request, &response); // 服务端回调填充响应体
    Buffer buf{};
    response.appendToBuffer(&buf); // 填充响应行和响应头

    conn->sendData(&buf);
    if (response.getNeedCloseConnection())
    {
        conn->shutdown();
    }
}

void HttpServer::start()
{
    LOG_INFO("HttpServer[%s] starts listening on %s...",
             this->tcpServer_.getName().c_str(), this->tcpServer_.getIpPort().c_str());
    this->tcpServer_.start();
}

// HTTPS用到
HttpServer::HttpServer(EventLoop *loop,
                       const InetAddress &listenAddr,
                       TcpServer::ListenOption listenOpt,
                       const std::string &threadName,
                       bool useSsl)
    : tcpServer_(loop, listenAddr, listenOpt, threadName),
      useSsl_(useSsl),
      httpCallback_(std::bind(&HttpServer::handleRequest2, this, std::placeholders::_1, std::placeholders::_2))
{
    this->tcpServer_.setThreadNum(3);

    this->tcpServer_.setConnectionCallback(
        std::bind(&HttpServer::onConnectionCallback2, this, std::placeholders::_1));
    this->tcpServer_.setReadWriteCallback(
        std::bind(&HttpServer::onReadWriteCallback2, this,
                  std::placeholders::_1,
                  std::placeholders::_2,
                  std::placeholders::_3));
}

void HttpServer::handleRequest2(const HttpRequest &request, HttpResponse *response)
{
    try
    {
        // 请求前的中间件处理
        HttpRequest mutableReq = request;
        this->middlewareChain_.processBefore(mutableReq);

        // 路由处理
        if (!this->router_.route(mutableReq, response))
        {
            LOG_INFO("URL: %s %s not match router", request.getMethodName().c_str(), request.getPath().c_str());

            response->setStatusCode(HttpResponse::StatusCode::NotFound404);
            response->setStatusMessage("Not Found");
            response->setNeedCloseConnection(true);
        }

        // 响应后的中间件处理
        this->middlewareChain_.processAfter(*response);
    }
    catch (const HttpResponse &res)
    {
        // 处理中间件抛出的响应（如CORS预检请求）
        // CORS Options响应会不继续中间件链直接throw，这里接住
        *response = res;
    }
    catch (const std::exception &e)
    {
        response->setStatusCode(HttpResponse::StatusCode::InternalServerError500);
        response->setBody(e.what());
    }
}

void HttpServer::onConnectionCallback2(const TcpConnectionPtr &tcpConn)
{
    if (tcpConn->isConnected())
    {
        if (this->useSsl_)
        {
            auto sslConn = std::make_unique<SslConnection>(tcpConn, this->sslCtx_.get());
            sslConn->setMessageCallback(
                std::bind(&HttpServer::onReadWriteCallback2, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
            this->tcpToSslConns_[tcpConn] = std::move(sslConn);
            this->tcpToSslConns_[tcpConn]->startHandshake();
        }
        tcpConn->setUserData(HttpContext()); // 保存用户数据
    }
    else
    {
        if (this->useSsl_)
        {
            this->tcpToSslConns_.erase(tcpConn);
        }
    }
}

void HttpServer::onReadWriteCallback2(const TcpConnectionPtr &tcpConn, Buffer *buf, Timestamp receiveTime)
{
    try
    {
        // 这层只是判断是否支持ssl
        if (this->useSsl_)
        {
            LOG_INFO("onReadWriteCallback2 this->useSsll_ is true");

            // 1.查找对应的SSL连接
            auto it = this->tcpToSslConns_.find(tcpConn);
            if (it != this->tcpToSslConns_.end())
            {
                LOG_INFO("onReadWriteCallback2 this->tcpToSslConns_ is not empty");

                // 2.SSL连接处理数据
                it->second->onRead(tcpConn, buf, receiveTime);

                // 3.如果SSL握手还未完成，直接返回
                if (!it->second->isHandshakeCompleted())
                {
                    LOG_INFO("onReadWriteCallback2 SSL is not handshake completed");
                    return;
                }

                // 4.从SSL连接的解密缓冲区获取数据
                Buffer *decryptedBuf = it->second->getDecryptedBuffer();
                if (decryptedBuf->getReadableSize() == 0)
                    return; // 没有解密后的数据

                // 5.使用解密后的数据进行HTTP处理
                buf = decryptedBuf; // buf指向解密后的数据
                LOG_INFO("onReadWriteCallback2 decryptedBuf is not empty");
            }
        }

        // HttpContext解析出buf中的请求报文，并把报文的关键信息封装到HttpRequest
        // HttpContext *httpContext = std::any_cast<HttpContext>(tcpConn->getMutableUserData());
        std::unique_ptr<HttpContext> httpContext(new HttpContext);
        if (!httpContext->parseRequest(buf, receiveTime))
        {
            tcpConn->sendData("HTTP/1.1 400 Bad Request\r\n\r\n");
            tcpConn->shutdown();
        }
        // 解析出完整数据包才封装响应报文
        if (httpContext->isRequestParseStateGotAll())
        {
            this->handleRequest(tcpConn, httpContext->getRequest());
            httpContext->reset();
        }
    }
    catch (const std::exception &e)
    {
        LOG_INFO("Exception in onReadWriteCallback2: %s", e.what());
        tcpConn->sendData("HTTP/1.1 400 Bad Request\r\n\r\n");
        tcpConn->shutdown();
    }
}

void HttpServer::setSslConfig(const SslConfig &sslConfig)
{
    if (this->useSsl_)
    {
        this->sslCtx_ = std::make_unique<SslContext>(sslConfig);
        if (!this->sslCtx_->init())
        {
            LOG_ERROR("Failed to init SSL context");
            ::abort();
        }
    }
}